﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using POSPlus.QueryCreator;
using System.Data.SqlClient;
using System.Configuration;
using POSPlus.QueuedBackgroundWorker;
using System.Text.RegularExpressions;
using POSPlus.MvcPassiveView;
using POSPlus.DatabaseOperations;
using POSPlus.EZBarTender.DatabaseOperations;
using System.Diagnostics;
using Util;
using EZBarTender.DataAccess.DAO;
using EZBarTender.DataAccess.Service;
using EZBarTender.DataAccess.Mapping;

namespace POSPlus.EZBarTender
{
    /// <summary>
    /// <para>Main class and form screen used to view all the batches on a given server.
    /// This class also identifies each batch as a Regular, Reg New Item, AD, BH/BR,
    /// DSD, Seasonal, Discontinued, Eggs, Liquor, EDLP, Catalina and the other 
    /// unidentified ones.</para>
    /// 
    /// <para>Printing is limited from this screen based upon what a batch
    /// is classified as.</para>
    /// 
    /// <para>It includes a double click feature that displays all items
    /// in a batch split into two groups, printable and non-printable.  You also have
    /// the ability to print from the pop up from this double click.</para>
    /// 
    /// <para>The All tab does not allow printing, but has a useful feature in that it
    /// displays how the batch was classified.</para>
    /// 
    /// <para>This new version includes threaded queries to prevent the user experiencing
    /// the long load time from the original and prevents 'locking up'.</para>
    /// </summary>
    public partial class BatchPrinter : Form
    {
        #region Attributes
        private BackgroundableDataGridView _dataGridView;
        private DataSet _tables;
        private Query _query;
        private SqlConnection _sqlConnection;
		private String _corpConnectionString;
        private SqlDataAdapter _sqlAdapter;
        private string _sqlConnectionString;
        private ProductsTable _productsTable;
        private BatchFilter _batchFilter;
        private PrinterController _printManager;
        private const string _prodBatsView = "POSplus_TagLoc_ProdBats";

        private ApplicationConfig appConfig;

        private Queue<QueueItem<SqlCommand>> _queryQueue = new Queue<QueueItem<SqlCommand>>();

        public string BarTenderTableName = "BarTenderPrintQueue";
		
        // Fields and Types to create the table
        public string[] LabelFields = new string[] {
            "Description","Vendor","Cert_Code","AvgDailyMovement","Pack","Size","Unit_NP",
            "UOM","Hosted","PriceMethod","Normal_Price","GroupPrice","Quantity","UPC",
            "LocAisle","LocBlock","LocSeq","PrintDate","SpecialPriceMethod","Special_Price",
            "SpecialGroupPrice","SpecialQuantity","PalletCode","Unit_SP","WhereToBuy",
            "Start_Date","End_Date","Rehang","DealEndDate","TagType", "BatchNo", "JobName"};
        public string[] LabelTypes = new string[] { "varchar(30)", "int", "varchar(15)", "float", "smallint", "varchar(9)", "float", "varchar(9)", "int", "smallint", "money", "money", "smallint", "varchar(13)", "int", "int", "int", "DATETIME", "smallint", "money", "money", "smallint", "int", "float", "varchar(9)", "DATETIME", "DATETIME", "varchar(9)","DATETIME","varchar(5)", "varchar(25)","varchar(65)" };

        // INSERT INTO POSPlus_<ComputerName>_BarTender
        // (EverythingFields)
        // VALUES
        // (EverythingSelect)

        // This is for the select statement in 
        public string[] EverythingSelect = new string[] {
            "UPC","Description","Cert_Code","PriceMethod","GroupPrice",
            "Normal_Price","Quantity","Pack","Size","Vendor","Hosted",
            "LocAisle","LocBlock","LocSeq","Unit_NP","UOM","AvgDailyMovement",
            "BatchNo","SpecialPriceMethod","Special_Price","SpecialGroupPrice",
            "SpecialQuantity","Unit_SP","Rehang","WhereToBuy","Start_Date",
            "End_Date","DealEndDate","PalletCode"};

        // These are the fields in the table
        public string[] EverythingFields = new string[] { 
            "UPC","Description","Cert_Code","PriceMethod","GroupPrice",
            "Normal_Price","Quantity","Pack","Size","Vendor","Hosted",
            "LocAisle","LocBlock","LocSeq","Unit_NP","UOM","AvgDailyMovement",
            "BatchNo","SpecialPriceMethod","Special_Price","SpecialGroupPrice",
            "SpecialQuantity","Unit_SP","Rehang","WhereToBuy","Start_Date",
            "End_Date","DealEndDate","PalletCode","TagType","JobName"};
		public String[] RegularFields = new String[] {
			"UPC","Description","Cert_Code","PriceMethod","GroupPrice",
			"Normal_Price","Quantity","Pack","Size","Vendor","Hosted",
			"LocAisle","LocBlock","LocSeq","Unit_NP","UOM","AvgDailyMovement",
			"BatchNo","TagType","JobName"};
		
        private String[] regularWithRSelect = new String[] {
            "r.UPC","r.Description","r.Cert_Code","r.PriceMethod","r.GroupPrice",
            "r.Normal_Price","r.Quantity","r.Pack","r.Size","r.Vendor","r.Hosted",
            "r.LocAisle","r.LocBlock","r.LocSeq","r.Unit_NP","r.UOM","r.AvgDailyMovement"};
        private String[] regularSelect = new String[] {
            "UPC","Description","Cert_Code","PriceMethod","GroupPrice","Normal_Price",
            "Quantity","Pack","Size","Vendor","Hosted","LocAisle","LocBlock","LocSeq",
            "Unit_NP","UOM","AvgDailyMovement"};

        private String[] specialWithSSelect = new String[] {
            "s.BatchNo","s.SpecialPriceMethod","s.Special_Price","s.SpecialGroupPrice",
            "s.SpecialQuantity","s.Unit_SP","s.Rehang","s.WhereToBuy","s.Start_Date",
            "s.End_Date","s.DealEndDate","s.PalletCode"};

        private String[] specialSelect = new String[] {
            "BatchNo","SpecialPriceMethod","Special_Price","SpecialGroupPrice",
            "SpecialQuantity","Unit_SP","Rehang","WhereToBuy","Start_Date","End_Date",
            "DealEndDate","LocAisle","LocBlock","LocSeq","UPC","PalletCode"};

		ON on = new ON(new String[] {"r.UPC = s.UPC","ISNULL(r.LocAisle, 1) = ISNULL(s.LocAisle,1)","ISNULL(r.LocBlock,2) = ISNULL(s.LocBlock,2)",
			"ISNULL(r.LocSeq,3) = ISNULL(r.LocSeq,3)"}, "AND");

		OrderBy orderby = new OrderBy(new String[] { "s.Rehang", "ISNULL(r.LocAisle,9999999)", "r.LocBlock", "r.LocSeq", "r.UPC" });
		OrderBy regularOrderby = new OrderBy(new String[] {"Rehang","ISNULL(LocAisle,9999999)","LocBlock","LocSeq","UPC"});
        private Dictionary<string, TagType> _tagTypes;

		private BackgroundWorker _printManagerImport;
        #endregion

        #region Constructors

        /// <summary>
        /// <para>Default constructor for the BatchPrinter.  It initializes all the Forms components,
        /// creates the dataset with all the necessary tables and preps the SQL Connection String that
        /// will be used through out the program.</para>
        /// </summary>
        public BatchPrinter(String connectionString, string corpConnectionString)
        {
            InitializeComponent();
            InitialGridView();

            //BarTenderTableName = "POSplus_" + System.Environment.MachineName + "_BarTender";
			BarTenderTableName = "POSplus_TagPrinting";
            BarTenderTableName = Regex.Replace(BarTenderTableName, @"[\W-]","_");

            // Form components.

            // Create the data set and tables.
            _tables = new DataSet();
            _tables.Tables.Add("All");
            _tables.Tables.Add("Regular");
            _tables.Tables.Add("New Items");
            _tables.Tables.Add("AD");
            _tables.Tables.Add("BH/BR");
            _tables.Tables.Add("DSD");
            _tables.Tables.Add("Seasonal");
            _tables.Tables.Add("Discontinued");
            _tables.Tables.Add("Eggs");
            _tables.Tables.Add("Liquor");
            _tables.Tables.Add("EDLP");
            _tables.Tables.Add("Catalina");
            _tables.Tables.Add("Unidentified");
            _tables.Tables.Add("Temp");


            _tagTypes = new Dictionary<string, TagType>();
            _tagTypes.Add("All", TagType.NoTag);
            _tagTypes.Add("Regular", TagType.Regular);
            _tagTypes.Add("New Items", TagType.Regular);
            _tagTypes.Add("AD", TagType.SuperSale);
            _tagTypes.Add("BH/BR", TagType.SpecialDeal);
            _tagTypes.Add("DSD", TagType.SpecialDeal);
            _tagTypes.Add("Seasonal", TagType.SpecialDeal);
            _tagTypes.Add("Discontinued", TagType.NowEvenLower);
            _tagTypes.Add("Eggs", TagType.Regular);
            _tagTypes.Add("Liquor", TagType.SpecialDeal);
            _tagTypes.Add("EDLP", TagType.SmartBuy);
            _tagTypes.Add("Catalina", TagType.BonusBucks);
			_tagTypes.Add("Unidentified", TagType.NoTag);

            // Retrieve the SQL connection information from the application settings.
            string server = ConfigurationManager.AppSettings["SQLServer"];
            string user = ConfigurationManager.AppSettings["SQLUser"];
            string password = ConfigurationManager.AppSettings["SQLPassword"];
            string database = ConfigurationManager.AppSettings["SQLDatabase"];

			_corpConnectionString = corpConnectionString;
			
			// Build the SQL Connection String.
            _sqlConnectionString = "Data Source=" + server + ";";
            _sqlConnectionString += "User ID=" + user + ";";
            _sqlConnectionString += "Password=" + password + ";";
            _sqlConnectionString += "Initial Catalog=" + database + ";";

			_sqlConnectionString = connectionString;
			_printManagerImport = new BackgroundWorker();
			_printManagerImport.DoWork += new DoWorkEventHandler(_printManagerImport_DoWork);
			_printManagerImport.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_printManagerImport_RunWorkerCompleted);
        }

		public BatchPrinter(string connectionString, string corpConnectionString, Point location)
			: this(connectionString, corpConnectionString)
		{
			Location = location;
		}

		public BatchPrinter(string connectionString, string corpConnectionString, int x, int y)
			: this(connectionString, corpConnectionString)
		{
			Location = new Point(x, y);
		}

        public BatchPrinter(ApplicationConfig appConfig) :
            this(appConfig.LocalConnectionString, appConfig.CorpConnectionString)
        {
            this.appConfig = appConfig;
            printRehangsCheckbox.Checked = appConfig.PrintRehangs;
        }

        public BatchPrinter(ApplicationConfig appConfig, int x, int y)
            : this(appConfig.LocalConnectionString, appConfig.CorpConnectionString, x, y)
        {
            this.appConfig = appConfig;
            printRehangsCheckbox.Checked = appConfig.PrintRehangs;
        }
        #endregion
        /// <summary>
        /// <para>Creates the query. Then starts the background worker to execute the
        /// query.</para>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _batchPrinter_Load(object sender, EventArgs e)
        {
            // Counting all the 'Y' print tag flags in the Product Batches view.
            Query one = new Query(new Select(
                new string[] { "BatchNo, COUNT(SVTregPrintTagFlag) AS Printable" }),
                new From("POSplus_TagLoc_ProdBats"), 
                new Where("SVTregPrintTagFlag = 'Y'"), 
                new GroupBy(new string[] { "BatchNo", "SVTregPrintTagFlag" }));

            // Counts all the 'N' print tag flags in the Product Batches view.
            Query two = new Query(new Select(
                new string[] { "BatchNo", "COUNT(SVTregPrintTagFlag) AS NonPrintable" }),
                new From("POSplus_TagLoc_ProdBats"), 
                new Where("SVTregPrintTagFlag = 'N'"),
                new GroupBy(new string[] { "BatchNo", "SVTregPrintTagFlag" }));

            // Create the join to combine the two previous queries with all the information needed to be viewed.
            _query = new Query(new Select(
                new string[] {"a.BatchNo","a.Description","COALESCE(Printable,0) AS Printable","COALESCE(NonPrintable,0) AS NonPrintable",
                    "a.StartDate","a.EndDate","a.AppliedWhen","a.TagPrintDate AS LastPrinted"}),
                    new From("ProductBatchesHeader a\nFULL JOIN (" + one.ToString() + ") b\nON a.BatchNo = b.BatchNo\nFULL JOIN (" + two.ToString() + ") c\nON a.BatchNo = c.BatchNo"),
                    new OrderBy("a.BatchNo"));
            _query.AddWhereExpression("a.BatchNo IS NOT NULL");

			Console.WriteLine("##################### Get all batches ###################");
			Console.WriteLine(_query.ToString());
			Console.WriteLine("#########################################################");

            // Show the loading picture box.
            _pictureBox.Visible = true;
			_queryWork.RunWorkerAsync(new string[] { _query.ToString(), "All" });

			//// Start the work in a thread.

			//// Create the table we will be working with
			//SQLColumn[] cols = new SQLColumn[LabelFields.Length];
			//for (int i = 0; i < cols.Length; i++)
			//{
			//    cols[i] = new SQLColumn(LabelFields[i], LabelTypes[i]);
			//}

			
			//Console.WriteLine("################# CREATE TABLE ##################");
			//Console.WriteLine(TableOperation.CreateTable(BarTenderTableName, cols));
			//Console.WriteLine("#################################################");
			//AddQueue(new SqlCommand(TableOperation.CreateTable(BarTenderTableName, cols), new SqlConnection(_sqlConnectionString)), null);
        }

        private void BatchPrinter_FormClosing(object sender, FormClosingEventArgs e)
        {
            _tables.Dispose();
        }

        /// <summary>
        /// <para>The workhorse of this form it opens the SQL Connection, executes the query from the load event handler,
        /// fills the 'All Items' table in the data set and sets the result to the table name.</para>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">Needs a string[] with 2 items in it to work. The first is the query to be executed
        /// and the second is the name of the table to put the information in.</param>
		private void _queryWorker_DoWork(object sender, DoWorkEventArgs e)
		{
			// Get the arguments.
			string[] arguments = (string[])e.Argument;

			using (SqlConnection connection = new SqlConnection(_sqlConnectionString))
			{
				_tables.Tables[arguments[1]].Reset();
				connection.Open();
				using (SqlDataAdapter adapter = new SqlDataAdapter(arguments[0], connection))
				{
					adapter.Fill(_tables.Tables[arguments[1]]);
				}
			}

			// Set the result to the name of the table.
			e.Result = arguments[1];
		}

        /// <summary>
        /// </para>Called immediately after the DoWork event handler is called.  Check to see if we worked on a double click
        /// or if we loaded the DataGridView.</para>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _queryWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // If we used the 'Temp' table then we doubled clicked.
            if (((string)e.Result).Equals("Temp"))
            {
                string title = "";
                foreach (DataGridViewRow row in _dataGridView.SelectedRows)
                    title += row.Cells["BatchNo"].Value + ", ";

                if (title.Length > 0)
                    title = title.Substring(0, title.Length - 2);

                // Show the dialog.
                DialogResult result = BatchSummary.ShowDialog(_tables.Tables["Temp"], title);
                /*
                if (result == System.Windows.Forms.DialogResult.OK)
                {
                    MessageBox.Show("OK");
                }
                else
                {
                    MessageBox.Show("Not OK");
                }
                 */
            }
            else
            {
                // Place the batches in the correct tables.
                identifyBatches();

                // Remove the DataSource from the DataGridView and the load the given table.
                _dataGridView.DataSource = null;
                _dataGridView.DataSource = _tables.Tables[(string)e.Result];
            }

            // Done working so hide the loading image.
            _pictureBox.Visible = false;
        }

        /// <summary>
        /// Sets up the DataGridView with some extra settings for this form.
        /// </summary>
        public void InitialGridView()
        {
            // Create the DataGridView set the size and add the double click event handler to it.
            _dataGridView = new BackgroundableDataGridView();
            _dataGridView.Height = _batchesTabCtrl.SelectedTab.Height - 5;
            _dataGridView.Width = _batchesTabCtrl.SelectedTab.Width - 5;
           
            //_dataGridView.Size = new System.Drawing.Size(670, 458);
            _dataGridView.DoubleClick += new EventHandler(_dataGridView_DoubleClick);
            _tabPageAll.Controls.Add(_dataGridView);
			_dataGridView.SelectionChanged += new EventHandler(_dataGridView_SelectionChanged);
			_dataGridView.RowsAdded += new DataGridViewRowsAddedEventHandler(_dataGridView_RowsAdded);
			_dataGridView.RowsRemoved += new DataGridViewRowsRemovedEventHandler(_dataGridView_RowsRemoved);
        }

		void _dataGridView_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
		{
			if (_dataGridView.Rows.Count < 1)
			{
				btnBatchFilter.Enabled = false;
				_btnAddToPrintController.Enabled = false;
			}
			else if(_batchesTabCtrl.SelectedTab.Text != "All")
			{
				btnBatchFilter.Enabled = true;
				_btnAddToPrintController.Enabled = true;
			}
		}

		void _dataGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
		{
			if (_dataGridView.Rows.Count < 1)
			{
				btnBatchFilter.Enabled = false;
				_btnAddToPrintController.Enabled = false;
			}
			else if (_batchesTabCtrl.SelectedTab.Text != "All")
			{
				btnBatchFilter.Enabled = true;
				_btnAddToPrintController.Enabled = true;
			}
		}

		void _dataGridView_SelectionChanged(object sender, EventArgs e)
		{
			if (_dataGridView.Rows.Count < 1)
			{
				btnBatchFilter.Enabled = false;
				_btnAddToPrintController.Enabled = false;
			}
			else if (_batchesTabCtrl.SelectedTab.Text != "All")
			{
				btnBatchFilter.Enabled = true;
				_btnAddToPrintController.Enabled = true;
			}
		}

        /// <summary>
        /// <para>We got a double click so we need to load the Batch Summary Popup.</para>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _dataGridView_DoubleClick(object sender, EventArgs e)
        {
            batchSummaryPopup();
        }

        /// <summary>
        /// <para>Sorts the batches from the 'All' table into the correct tables based upon the batch number.</para>
        /// </summary>
        private void identifyBatches()
        {
            // Add all the columns from the 'All' table to the others.
            foreach (DataColumn col in _tables.Tables["All"].Columns)
            {
                _tables.Tables["Regular"].Columns.Add(col.ColumnName);
                _tables.Tables["New Items"].Columns.Add(col.ColumnName);
                _tables.Tables["AD"].Columns.Add(col.ColumnName);
                _tables.Tables["BH/BR"].Columns.Add(col.ColumnName);
                _tables.Tables["DSD"].Columns.Add(col.ColumnName);
                _tables.Tables["Seasonal"].Columns.Add(col.ColumnName);
                _tables.Tables["Discontinued"].Columns.Add(col.ColumnName);
                _tables.Tables["Eggs"].Columns.Add(col.ColumnName);
                _tables.Tables["Liquor"].Columns.Add(col.ColumnName);
                _tables.Tables["EDLP"].Columns.Add(col.ColumnName);
                _tables.Tables["Catalina"].Columns.Add(col.ColumnName);
                _tables.Tables["Unidentified"].Columns.Add(col.ColumnName);
                _tables.Tables["Temp"].Columns.Add(col.ColumnName);
            }

            _tables.Tables["All"].Columns.Add("IdentifiedAs");

            // For all the rows in the 'All' table...
            foreach (DataRow row in _tables.Tables["All"].Rows)
            {
                // If goes on a regular label the put it in regular unless the description contains 'A-NEW ITEMS'.
                if (row["BatchNo"].ToString().ToLower().Contains("_ppc_") || row["BatchNo"].ToString().ToLower().Contains("_miscchg_"))
                {
                    if (row["Description"].ToString().StartsWith("NEW ITEMS", StringComparison.CurrentCultureIgnoreCase))
                    {
                        _tables.Tables["New Items"].ImportRow(row);
                        row["IdentifiedAs"] = "New Item";
                    }
                    else
                    {
                        _tables.Tables["Regular"].ImportRow(row);
                        row["IdentifiedAs"] = "Regular";
                    }
                }
                // If the batch starts with the letters 'ad' (not case sensitive) then put it in the 'AD' table.
                else if (row["BatchNo"].ToString().StartsWith("AD", StringComparison.CurrentCultureIgnoreCase))
                {
                    _tables.Tables["AD"].ImportRow(row);
                    row["IdentifiedAs"] = "AD";
                }
                // If the batch starts with 'BackRoom' (not case sensitive) or 'BuyHoldWareHouse' (ncs)
                // then put it in the 'BH/BR' table.
                else if (row["BatchNo"].ToString().StartsWith("BackRoom", StringComparison.CurrentCultureIgnoreCase) ||
                   row["BatchNo"].ToString().StartsWith("BuyHoldWareHouse", StringComparison.CurrentCultureIgnoreCase))
                {
                    _tables.Tables["BH/BR"].ImportRow(row);
                    row["IdentifiedAs"] = "BH/BR";
                }
                // If the batch contains the letters 'dsd' (ncs) then put it in the DSD table.
                else if (row["BatchNo"].ToString().ToLower().Contains("dsd"))
                {
                    _tables.Tables["DSD"].ImportRow(row);
                    row["IdentifiedAs"] = "DSD";
                }
                // If the batch starts with 'Seasonal' (ncs) then put it in the seasonal table.
                else if (row["BatchNo"].ToString().StartsWith("Seasonal", StringComparison.CurrentCultureIgnoreCase))
                {
                    _tables.Tables["Seasonal"].ImportRow(row);
                    row["IdentifiedAs"] = "Seasonal";
                }
                // If the batch starts with 'Discontinued' then put it in the discontinued table.
                    // TODO probably need to change this to starting with 'disco'
                else if (row["BatchNo"].ToString().StartsWith("Disco", StringComparison.CurrentCultureIgnoreCase))
                {
                    _tables.Tables["Discontinued"].ImportRow(row);
                    row["IdentifiedAs"] = "Discontinued";
                }
                // If the batch contains the letters 'egg' (ncs) then put it in the eggs table.
                else if (row["BatchNo"].ToString().ToLower().Contains("egg"))
                {
                    _tables.Tables["Eggs"].ImportRow(row);
                    row["IdentifiedAs"] = "Eggs";
                }
                // If the batch contains the letters 'liquor' (ncs) then put it in the liquor table.
                else if (row["BatchNo"].ToString().ToLower().Contains("liquor"))
                {
                    _tables.Tables["Liquor"].ImportRow(row);
                    row["IdentifiedAs"] = "Liquor";
                }
                // If the name contains 'edlp' (ncs) then put it in the EDLP table.
                else if (row["BatchNo"].ToString().ToLower().Contains("edlp"))
                {
                    _tables.Tables["EDLP"].ImportRow(row);
                    row["IdentifiedAs"] = "EDLP";
                }
                // If it contains 'cata' then put it in the Catalina table.
                else if (row["BatchNo"].ToString().ToLower().Contains("cata"))
                {
                    _tables.Tables["Catalina"].ImportRow(row);
                    row["IdentifiedAs"] = "Catalina";
                }
                // Otherwise stick it in unidentified.
                else
                {
                    _tables.Tables["Unidentified"].ImportRow(row);
                    row["IdentifiedAs"] = "Unidentified";
                }
            }
        }

        /// <summary>
        /// <para>Change the datasource when the tab changes and move the DataGridView to the correct tab.</para>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _batchesTabCtrl_SelectedIndexChanged(object sender, EventArgs e)
        {
			
			_dataGridView.DataSource = _tables.Tables[_batchesTabCtrl.SelectedTab.Text];

			if (_batchesTabCtrl.SelectedTab.Text == "All")
			{
				_btnAddToPrintController.Enabled = false;
				_btnBatchFilter.Enabled = false;
			}
			else
			{
				_btnAddToPrintController.Enabled = true;
				_btnBatchFilter.Enabled = true;
			}
			
            _batchesTabCtrl.SelectedTab.Controls.Remove(_dataGridView);
            _batchesTabCtrl.SelectedTab.Controls.Add(_dataGridView);
        }

        /// <summary>
        /// <para>Executes a query to load all the items in the selected batch.</para>
        /// </summary>
        private void batchSummaryPopup()
        {
            // Select all from Product Batches where the Batch Number has been selected.
            _query = new Query(
                new Select(new string[] { "UPC", "Description", "Size", "Cert_Code", "SVTregPrintTagFlag", "Hosted" }),
                new From("POSplus_TagLoc_ProdBats"));

            List<string> ors = new List<string>();
            foreach (DataGridViewRow row in _dataGridView.SelectedRows)
                ors.Add("BatchNo = '" + row.Cells["BatchNo"].Value + "'");

            _query.AddWhereExpressions("AND", ors.ToArray(), "OR");

            // Start work on the query.
            _queryWork.RunWorkerAsync(new string[] { _query.ToString(), "Temp" });
        }

        /// <summary>
        /// <para>Changes to the Products Table screen keeping the size and location of this form.</para>
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnProductsTable_Click(object sender, EventArgs e)
        {
            // If the ProductsTable doesn't exist create it.
			if (_productsTable == null)
			{
				_productsTable = new ProductsTable(this, Location.X, Location.Y, Width, Height);
				_productsTable.JobAdded += new ProductsTable.JobAddedEventHandler(_productsTable_JobAdded);
			}
			else
			{
				// Set the location and size to this form's.
				_productsTable.Location = Location;
				_productsTable.Size = Size;
			}
            
            // Make the Products Table visible.
            _productsTable.Visible = true;
            Visible = false;
        }

		void _productsTable_JobAdded(object sender, EventArgs e)
		{
			if (OnJobAdded != null)
				OnJobAdded(this, EventArgs.Empty);
		}

        private void btnBatchFilter_Click(object sender, EventArgs e)
        {
            bool future = false;
            foreach (DataGridViewRow row in _dataGridView.SelectedRows)
            {
                if (row.Cells["BatchNo"].Value.ToString().Equals("DSDwareHousePricing"))
                {
                    if(currentOrFuture() == System.Windows.Forms.DialogResult.Yes)
                        future = true;
                }
            }

            string tablename;
            if (future) tablename = "POSplus_TagLoc_DSD_FPB";
            else tablename = "POSplus_TagLoc_ProdBats";

			List<String> batchNos = new List<string>();
			foreach (DataGridViewRow row in _dataGridView.SelectedRows)
			{
				batchNos.Add(row.Cells["BatchNo"].Value.ToString());
			}


            if (_batchesTabCtrl.SelectedTab.Text == "Discontinued")
            {
                DialogResult result = DiscoDialog.ShowDialog(1);
                if (result == DialogResult.Yes)
                    _batchFilter = new BatchFilter(this, TagType.RegularDiscontinued, tablename, batchNos.ToArray());
                else if (result == DialogResult.OK)
                    _batchFilter = new BatchFilter(this, TagType.NowEvenLower, tablename, batchNos.ToArray());
            }
			else if (_batchesTabCtrl.SelectedTab.Text == "Unidentified")
			{
				SelectTagTypeDialog dialog = new SelectTagTypeDialog();
				DialogResult result = dialog.ShowDialog();
				if (result == DialogResult.OK)
					_batchFilter = new BatchFilter(this, dialog.Type, tablename, batchNos.ToArray());
			}
			else
			{
				_batchFilter = new BatchFilter(this, _tagTypes[_batchesTabCtrl.SelectedTab.Text], tablename, batchNos.ToArray());
			}
			_batchFilter.JobAdded += new BatchFilter.JobAddedEventHandler(_batchFilter_JobAdded);
            _batchFilter.Visible = true;
            Visible = false;
        }

		void _batchFilter_JobAdded(object sender, EventArgs e)
		{
			if (OnJobAdded != null)
				OnJobAdded(this, EventArgs.Empty);
		}

        public string ConnectionString
        {
            get { return _sqlConnectionString; }
        }

        public PrinterController PrintJobManager
        {
            get { return _printManager; }
            set { _printManager = value; }
        }
		
		void _printManagerImport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			if (e.Result != null && e.Result.ToString().StartsWith("Unable to"))
			{
				MessageBox.Show(this, e.Result.ToString(), "Print Manager Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			_btnAddToPrintController.Text = "Add To Print Manager";
			_btnAddToPrintController.Enabled = true;
			if (OnJobAdded != null)
				OnJobAdded(this, EventArgs.Empty);
		}

		void _printManagerImport_DoWork(object sender, DoWorkEventArgs e)
		{
			Object[] args = (Object[])e.Argument;
			List<String> batchNos = (List<String>)args[0];
            EZBT ezbartenderDS = new EZBT();
            PrintManagerService printManagerService = new PrintManagerService(appConfig.ConnectionString);

			foreach (String batchNo in batchNos)
			{
				String type =  GetDisplayType((String)args[1]);

				List<ProductBatches> bats = new List<ProductBatches>(1);
				if (batchNo.StartsWith("backroom", StringComparison.CurrentCultureIgnoreCase) || batchNo == "BuyHoldWareHouse") 
				{
					ModifiedDateDialog dialog = new ModifiedDateDialog();
					DialogResult result = dialog.ShowDialog();
                    ProductBatchService productBatchService = new ProductBatchService(appConfig.ConnectionString);

                    EZBT.ProductBatchDataTable batchDT = null;
                    if (result == DialogResult.OK)
                        batchDT = productBatchService.getAllByBatchNo(batchNo, 'Y', dialog.StartDate, dialog.EndDate, printRehangsCheckbox.Checked);
                    else if (result == DialogResult.Yes)
                        batchDT = productBatchService.getAllByBatchNo(batchNo, 'Y', printRehangsCheckbox.Checked);

                    else break;
                    PrintManagerMapper.Map(ezbartenderDS.PrintManagerDisplays, batchDT, type);
				}
				else if (batchNo == "DSDwareHousePricing")
				{
					DialogResult result = CurrentFutureDialog.ShowDialog("Current: Applied", "Future: Not Yet Applied");
					ModifiedDateDialog dates = new ModifiedDateDialog();
					DialogResult dateResult = dates.ShowDialog();

                    FutureProductBatchService futureBatchService = new FutureProductBatchService(appConfig.ConnectionString);

					if (result == DialogResult.Yes)
					{
						type = "6UPSDF";
                        EZBT.DSDFutureBatchDataTable batchDT = null;
                        if (dateResult == DialogResult.OK)
                            batchDT = futureBatchService.getByBatchNoAndModified(batchNo, "Y", dates.StartDate, dates.EndDate, printRehangsCheckbox.Checked);
                        else
                            batchDT = futureBatchService.getByBatchNo(batchNo, 'Y', printRehangsCheckbox.Checked);

                        PrintManagerMapper.Map(ezbartenderDS.PrintManagerDisplays, batchDT, type);
					}
					else if(result == DialogResult.OK)
					{
                        ProductBatchService productBatchService = new ProductBatchService(appConfig.ConnectionString);
                        EZBT.ProductBatchDataTable batchDT = null;
                        if (dateResult == DialogResult.OK)
                            batchDT = productBatchService.getAllByBatchNo(batchNo, 'Y', dates.StartDate, dates.EndDate, printRehangsCheckbox.Checked);
                        else
                            batchDT = productBatchService.getAllByBatchNo(batchNo, 'Y', printRehangsCheckbox.Checked);

                        PrintManagerMapper.Map(ezbartenderDS.PrintManagerDisplays, batchDT, type);
					}
				}
				else
				{
                    ProductBatchService productBatchService = new ProductBatchService(appConfig.ConnectionString);
                    EZBT.ProductBatchDataTable batchDT = productBatchService.getAllByBatchNo(batchNo, 'Y', printRehangsCheckbox.Checked);
                    PrintManagerMapper.Map(ezbartenderDS.PrintManagerDisplays, batchDT, type);
				}
                printManagerService.Persist(ezbartenderDS);
			}
		}

		private string GetDisplayType(String tabName)
		{
			switch (tabName)
			{
				case "Regular":
				case "New Items":
				case "Eggs": return "18UPREG";
				case "AD": return "6UPSS";
				case "Seasonal":
				case "Liquor": 
				case "BH/BR":
				case "DSD": return "6UPSD";
				case "EDLP": return "6UPSB";
				case "Catalina": return "6UPBB";
				case "Discontinued":
					DialogResult result = DiscoDialog.ShowDialog(this);
					if (result == DialogResult.OK)
					{
						return "6UPNEL";
					}
					else if (result == DialogResult.Yes)
					{
						return "18UPREGD";
					}
					else
						return "Fail";
				case "Unidentified":
					SelectTagTypeDialog dialog = new SelectTagTypeDialog();
					DialogResult res = dialog.ShowDialog();
					if (res == System.Windows.Forms.DialogResult.OK)
					{
						switch (dialog.Type)
						{
							case TagType.Regular: return "18UPREG";
							case TagType.RegularDiscontinued: return "18UPREGD";
							case TagType.SuperSale: return "6UPSS";
							case TagType.SpecialDeal: return "6UPSD";
							case TagType.NowEvenLower: return "6UPNEL";
							case TagType.SmartBuy: return "6UPSB";
							case TagType.BonusBucks: return "6UPBB";
							default: return "Fail";
						}
					}
					else
						return "Fail";
				default: return "Fail";
			}
		}

        /// <summary>
        /// Adds the selected batches to the Printer Controller.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _btnAddToPrintController_Click(object sender, EventArgs e)
        {
			_btnAddToPrintController.Enabled = false;
			_btnAddToPrintController.Text = "Adding...";

			if (_batchesTabCtrl.SelectedTab.Text == "Catalina")
			{
				foreach (DataGridViewRow row in _dataGridView.SelectedRows)
				{

				}
			}
			else
			{
				List<String> batchNos = new List<string>();
				foreach (DataGridViewRow row in _dataGridView.SelectedRows)
				{
					batchNos.Add(row.Cells["BatchNo"].Value.ToString());
				}
				Object[] args = new Object[2];
				args[0] = batchNos;
				args[1] = _batchesTabCtrl.SelectedTab.Text;
				_printManagerImport.RunWorkerAsync(args);
			}
        }
		
        public void AddQueue(SqlCommand sqlCommand, ProgressBar progressBar)
        {
            QueuedBackgroundWorker.QueuedBackgroundWorker.QueueWorkItem(
                _queryQueue,
                sqlCommand,
                args =>
                {
                    try
                    {
                        sqlCommand.Connection.Open();
                        int rowsAffected = sqlCommand.ExecuteNonQuery();
						Console.WriteLine("#### Rows Affected: {0}", rowsAffected);
                        return new { QueryCount = _queryQueue.Count, RowsAffected = rowsAffected };
                    }
                    catch (SqlException ex)
                    {
                        Console.WriteLine(ex.Message);
                        Console.WriteLine(sqlCommand.CommandText);
                    }
                    return new { QueryCount = -1, RowsAffected = -1 };
                },
                args =>
                {
                    if(progressBar != null)
                        progressBar.Value = args.Result.QueryCount;
                    sqlCommand.Connection.Close();
					sqlCommand.Dispose();
                });
        }
		
        private DialogResult currentOrFuture()
        {
            _sqlConnection = new SqlConnection(_sqlConnectionString);
            SqlCommand command = new SqlCommand("SELECT EndDate FROM ProductBatchesHeader WHERE BatchNo = 'DSDwareHousePricing'", _sqlConnection);
            SqlDataReader reader;
            string currentDate = "",
                futureDate = "";
            try
            {
                _sqlConnection.Open();
                reader = command.ExecuteReader();
                reader.Read();
                currentDate = reader[0].ToString();
                reader.Close();
            }
            catch (SqlException ex)
            {
                Console.WriteLine(ex.ToString());
                return DialogResult.Cancel;
            }
            finally
            {
                _sqlConnection.Close();
            }

            command = new SqlCommand("SELECT End_Date FROM POSplus_DSD_FuturePB GROUP BY End_Date", _sqlConnection);
            try
            {
                _sqlConnection.Open();
                reader = command.ExecuteReader();
                reader.Read();
                futureDate = reader["End_Date"].ToString();
                reader.Close();
            }
            catch (SqlException ex)
            {
                Console.WriteLine(ex.ToString());
                return DialogResult.Cancel;
            }
            finally
            {
                _sqlConnection.Close();
                _sqlConnection.Dispose();
            }

            return CurrentFutureDialog.ShowDialog("Current: " + currentDate, "Future: " + futureDate);
        }

        public BackgroundableDataGridView BGDataGridView
        {
            get { return _dataGridView; }
        }

        public TabControl Tabs
        {
            get { return _batchesTabCtrl; }
        }
/*
        public Queue<QueueItem<SqlCommand>> QueryQueue
        {
            get { return _queryQueue; }
        }
*/
		public delegate void JobAdded(Object sender, EventArgs e);
		public event JobAdded OnJobAdded;

        private void printRehangsCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            appConfig.PrintRehangs = printRehangsCheckbox.Checked;
        }
    }
}
